// // Copyright (c) 2009 All Right Reserved // // vl // // 2009-01-01 // Contains ... using System; using System.Text; using JetBrains.Annotations; namespace LargoCommon.Music { /// /// Note Length. /// public class NoteLength { #region Constructors /// /// Initializes a new instance of the class. /// /// The given tuple number. /// The given denominator. /// The given number of dots. /// The given tuple position. public NoteLength(TupleNumber givenTupleNumber, MusicalDenominator givenDenominator, int givenNumberOfDots, TuplePosition givenTuplePosition) { this.TupleNumber = givenTupleNumber; this.Denominator = givenDenominator; this.NumberOfDots = givenNumberOfDots; this.TuplePosition = givenTuplePosition; } /// /// Initializes a new instance of the class. /// /// The ticks. /// The whole note ticks. public NoteLength(int ticks, int wholeNoteTicks) { this.TupleNumber = TupleNumber.Single; this.NumberOfDots = 0; if (ticks == 0) { return; } //// var smallestLength = (float)wholeNoteTicks / 128; //// var denominator = 1; double baseTicks; if (ticks > wholeNoteTicks) { this.Denominator = MusicalDenominator.Whole; //// baseTicks = wholeNoteTicks; return; } else { var s = wholeNoteTicks / ticks; var r = Math.Log(s) / Math.Log(2); var cr = Math.Ceiling(r); if (cr > 7) { cr = 7; } double dr = Math.Pow(2, cr); this.Denominator = (MusicalDenominator)dr; baseTicks = Math.Round(wholeNoteTicks / dr); } var q = ticks / baseTicks; if (q > 1.4) { this.NumberOfDots = 1; } if (q > 1.7) { this.NumberOfDots = 2; } //// Temporarily - the aim is not register very short pauses ... if (this.Denominator == MusicalDenominator.D128Th) { this.Denominator = MusicalDenominator.None; } } #endregion #region Properties /// /// Gets the Denominator. /// /// Property description. public MusicalDenominator Denominator { get; } /// /// Gets the number of dots. /// /// /// The number of dots. /// public int NumberOfDots { get; } /// /// Gets the tuple. /// /// /// The tuple. /// public TuplePosition TuplePosition { get; } /// /// Gets or sets a value indicating whether [include pause]. Staccato... /// /// /// true if [include pause]; otherwise, false. /// public bool IncludePause { get; set; } /// /// Gets the tuple. /// /// /// The tuple. /// // ReSharper disable once UnusedAutoPropertyAccessor.Local private TupleNumber TupleNumber { [UsedImplicitly] get; } #endregion #region Factory methods /// /// Gets the length of the note. /// /// The ticks. /// The pause ticks. /// The whole note ticks. /// Returns value. public static NoteLength GetNoteLength(int ticks, int pauseTicks, int wholeNoteTicks) { //// if (ticks == 53 && pauseTicks == 120) { pauseTicks++; pauseTicks--; } if (pauseTicks == 0) { return new NoteLength(ticks, wholeNoteTicks); } var pauseLength = new NoteLength(pauseTicks, wholeNoteTicks); bool auxiliaryPause = (pauseLength.Denominator == MusicalDenominator.None) || ((pauseLength.Denominator >= MusicalDenominator.Sixteenth) && pauseTicks < 1.3 * ticks); NoteLength nl; // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression if (auxiliaryPause) { nl = new NoteLength(ticks + pauseTicks, wholeNoteTicks) { IncludePause = true }; } else { //// if (ticks == 1) { pauseTicks++; pauseTicks--; } nl = new NoteLength(ticks, wholeNoteTicks) { IncludePause = false }; } return nl; } #endregion #region String representation /// /// Returns a that represents this instance. /// /// /// A that represents this instance. /// public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append(this.Denominator); sb.AppendFormat(" {0} dots ", this.NumberOfDots); sb.Append(this.TuplePosition); return sb.ToString(); } #endregion } }